package com.jerome.fs.server.aggregation;

import com.jerome.fs.constants.AppConstant;
import com.jerome.fs.entities.WeatherVo;
import com.jerome.fs.http.HttpConstant;
import com.jerome.fs.http.HttpMethodEnum;
import com.jerome.fs.http.HttpStatus;
import com.jerome.fs.http.Request;
import com.jerome.fs.http.Response;
import com.jerome.fs.util.JsonUtil;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

/**
 * AggregationServer Http util
 *
 * @author Jerome
 * @date 2023/9/5
 */
public class AggregationHandleUtil {

    public static Response handle(ServerMqEvent serverEvent) throws IOException, IllegalAccessException, InvocationTargetException {
        if (HttpMethodEnum.GET.getCode().equalsIgnoreCase(serverEvent.getRequest().getMethod())) {
            // Handle GET request
            return handleGetRequest(serverEvent);
        } else if (HttpMethodEnum.PUT.getCode().equalsIgnoreCase(serverEvent.getRequest().getMethod())) {
            // Handle PUT request
            return handlePutRequest(serverEvent);
        } else {
            // Return 400 for other requests
            Response response = new Response();
            response.setCode(HttpStatus.HTTP_BAD_REQUEST);
            response.setStatus(HttpStatus.msg(response.getCode()));
            response.setVersion(HttpConstant.HTTP_VERSION);
            response.setMessage("");
            return response;
        }
    }

    /**
     * Handle GET request
     *
     * @param serverEvent
     * @throws IOException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private static Response handleGetRequest(ServerMqEvent serverEvent) throws IOException, InvocationTargetException, IllegalAccessException {
        Request request = serverEvent.getRequest();

        String responseStr = "";
        WeatherVo weatherVo = ContextUtil.getExpiringMap().get(serverEvent.getId());
        if (weatherVo != null) {
            weatherVo.setLatestTime(serverEvent.getLatestTime());
            responseStr = JsonUtil.writeValueAsString(weatherVo);
        }
        // Set response headers
        Response response = new Response();
        response.getHeaders().putAll(request.getHeaders());
        response.getHeaders().put("Content-Type", "application/json");
        response.getHeaders().put(AppConstant.LAMPORT_HEADER_NAME, serverEvent.getLatestTime() + "");
        // Write response text to the output stream
        response.setCode(HttpStatus.HTTP_OK);
        response.setStatus(HttpStatus.msg(HttpStatus.HTTP_OK));
        response.setVersion(HttpConstant.HTTP_VERSION);
        response.setMessage(responseStr);
        return response;

    }

    /**
     * Handle PUT request
     *
     * @throws IOException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private static Response handlePutRequest(ServerMqEvent serverEvent) throws IOException, IllegalAccessException, InvocationTargetException {
        Request request = serverEvent.getRequest();
        Response response = new Response();
        response.setVersion(request.getVersion());

        WeatherVo weatherVo = serverEvent.getWeatherVo();
        weatherVo.setLatestTime(serverEvent.getLatestTime());
        String responseStr = JsonUtil.writeValueAsString(weatherVo);
        // Save appended log
        ContextUtil.getLogger().write(String.format("%d\t%s\t%s\r\n", serverEvent.getLatestTime(), weatherVo.getId(), responseStr));
        WeatherVo oldWeatherVo = ContextUtil.getExpiringMap().get(weatherVo.getId());
        if (oldWeatherVo != null) {
            // Update
            response.setCode(HttpStatus.HTTP_OK);
        } else {
            // Add new
            response.setCode(HttpStatus.HTTP_CREATED);
        }
        //根据lamport clock判断是否更新
        if (oldWeatherVo == null || weatherVo.getLatestTime() > oldWeatherVo.getLatestTime()) {
            ContextUtil.getExpiringMap().put(weatherVo.getId(), weatherVo);
            ContextUtil.getRingBuffer().add(weatherVo);
            response.setMessage(responseStr);
        }else {
            //更新冲突
            response.setCode(HttpStatus.HTTP_CONFLICT);
            response.setMessage("The Last-Time header information you passed in is outdated");
        }
        // Set response headers
        response.getHeaders().put("Content-Type", "application/json");
        response.getHeaders().put(AppConstant.LAMPORT_HEADER_NAME, serverEvent.getLatestTime() + "");
        // Write response text to the output stream
        response.setStatus(HttpStatus.msg(response.getCode()));
        return response;
    }
}
